package com.immediatus.engine.modifier;


import com.immediatus.engine.contracts.Interpolator;
import com.immediatus.engine.interpolator.LinearInterpolator;

public abstract class BaseDurationModifier<T> extends BaseModifier<T>{
	private float _secondsElapsed;
	private final float _duration;
    private final Interpolator _interpolator;

	public BaseDurationModifier(final float duration_) {
		this._duration = duration_;
        this._interpolator = new LinearInterpolator();
	}

    public BaseDurationModifier(final float duration_, final Interpolator interpolator_) {
        this._duration = duration_;
        this._interpolator = interpolator_;
    }

	public BaseDurationModifier(final float duration_, final IModifierListener<T> listener_) {
		super(listener_);
		this._duration = duration_;
        this._interpolator = new LinearInterpolator();

	}

    public BaseDurationModifier(final float duration_, final IModifierListener<T> listener_, final Interpolator interpolator_) {
        super(listener_);
        this._duration = duration_;
        this._interpolator = interpolator_;

    }

	protected BaseDurationModifier(final BaseDurationModifier<T> modifier_) {
		this(modifier_._duration);
	}

	@Override
	public float getSecondsElapsed() {
		return this._secondsElapsed;
	}

	@Override
	public float getDuration() {
		return this._duration;
	}

	protected abstract void onManagedUpdate(final float secondsElapsed_, final T item_);

	protected abstract void onManagedInitialize(final T item_);

    protected Interpolator getInterpolator() {
        return _interpolator;
    }

	@Override
	public final float onUpdate(final float secondsElapsed_, final T item_) {
		if(this.isFinished()){
			return 0;
		} else {
			if(this._secondsElapsed == 0) {
				this.onManagedInitialize(item_);
				this.onModifierStarted(item_);
			}

			final float secondsElapsedUsed;
			if(this._secondsElapsed + secondsElapsed_ < this._duration) {
				secondsElapsedUsed = secondsElapsed_;
			} else {
				secondsElapsedUsed = this._duration - this._secondsElapsed;
			}

			this._secondsElapsed += secondsElapsedUsed;
			this.onManagedUpdate(this._secondsElapsed, item_);

			if(this._duration != -1 && this._secondsElapsed >= this._duration) {
				this._secondsElapsed = this._duration;
				this.setFinished(true);
				this.onModifierFinished(item_);
			}
			return secondsElapsedUsed;
		}
	}

	@Override
	public void reset() {
		this.setFinished(false);
		this._secondsElapsed = 0;
	}
}
